// created by noellynch
// May 8, 2009

package com.sceneworker.editors.proceduraltexturegeneratoreditor;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.concurrent.Callable;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import net.miginfocom.swing.MigLayout;

import com.jme.image.Texture;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.RenderState.StateType;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.ProceduralTextureGenerator;
import com.myjavautils.GenericUtils;
import com.myjavautils.swing.MigLayoutUtils;
import com.myjavautils.swing.SwingComponentFactory;
import com.sceneworker.app.globals.cacheobjects.TerrainAndHeightMapCacheObject;
import com.sceneworker.util.swing.imagelist.SimpleImageList;

public class ProcTextureGenPanel extends JPanel {
	
	private		TerrainAndHeightMapCacheObject		mcl_terrain;
	private		JDialog								mcl_dlg;
	private		JButton								mcl_create;
	private		ArrayList<ProcTextureStruct>		mcla_textures;
	private		GenPanel							mcl_genPanel;
	
	public	ProcTextureGenPanel(TerrainAndHeightMapCacheObject cl_ref, JDialog cl_dlg) {
		mcl_dlg = cl_dlg;
		mcl_terrain = cl_ref;
		mcla_textures = new ArrayList<ProcTextureStruct>();
		
		setLayout(new MigLayout("inset 5"));
		
		JPanel					lcl_panels = new JPanel(new MigLayout("inset 5"));
		ProcTexturesPanel		lcl_texturePanel = new ProcTexturesPanel();
		mcl_genPanel = new GenPanel();
		
		lcl_panels.add(lcl_texturePanel, "width 50%, height 100%");
		lcl_panels.add(mcl_genPanel, "width 50%, height 100%");
		
		add(lcl_panels, "width 100%, height 80%, wrap");
		
		JButton		lcl_done = SwingComponentFactory.makeAButton("Cancel");
		lcl_done.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mcl_dlg.setVisible(false);
			}
		});
		
		mcl_create = SwingComponentFactory.makeAButton("Create");
		mcl_create.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				createTexture();
				mcl_dlg.setVisible(false);
			}
		});
		mcl_create.setEnabled(false);
		
		MigLayoutUtils.makeRightAlignedButtonBar(this, lcl_done, mcl_create);
	}
	
	private	void	createTexture() {
		GameTaskQueueManager.getManager().update(new Callable<Void>() {
			public Void call() throws Exception {
				TerrainPage		lcl_terrain = mcl_terrain.getTerrain();
				TextureState	lcl_ts = (TextureState)lcl_terrain.getRenderState(StateType.Texture);
				
				if(lcl_ts == null) {
					lcl_ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
				}
				
				Texture lcl_texture = TextureManager.loadTexture(mcl_genPanel.getGeneratedTexture(),
						Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear, true);
				lcl_texture.setApply(Texture.ApplyMode.Combine);
				lcl_texture.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
				lcl_texture.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
				lcl_texture.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
				lcl_texture.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
				lcl_texture.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
				lcl_ts.setTexture(lcl_texture, 0);
				
				lcl_terrain.setRenderState(lcl_ts);
				
				lcl_terrain.updateRenderState();
				
				return null;
			}
		
		});
	}
	
	class	GenPanel extends JPanel {
		private		JTextField		mcl_size;
		public		ImageIcon		mcl_generatedTexture;
		
		public	GenPanel() {
			setLayout(new MigLayout("inset 5"));
			
			mcl_size = MigLayoutUtils.numberText(this, "Size", 256, false);
			JButton		lcl_gen = SwingComponentFactory.makeAButton("Preview");
			lcl_gen.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					int		li_size = Integer.parseInt(mcl_size.getText());
					
					ProceduralTextureGenerator		lcl_proc = new ProceduralTextureGenerator(mcl_terrain.getHeightMap());
					
					for(ProcTextureStruct lcl_procTexture : mcla_textures) {
						lcl_proc.addTexture(lcl_procTexture.mcl_image, lcl_procTexture.mi_low, lcl_procTexture.mi_optimal, lcl_procTexture.mi_high);
					}
					
					lcl_proc.createTexture(li_size);
					
					mcl_generatedTexture = lcl_proc.getImageIcon();
					
					mcl_create.setEnabled(true);
					repaint();
				}
			});
			add(lcl_gen, "wrap");
			
			JPanel		lcl_imagePanel = new JPanel() {

				@Override
				public Dimension getPreferredSize() {
					return new Dimension(256, 256);
				}

				@Override
				protected void paintComponent(Graphics cl_g) {
					cl_g.clearRect(0, 0, getWidth(), getHeight());
					
					if(mcl_generatedTexture != null) {
						cl_g.drawImage(mcl_generatedTexture.getImage(), 0, 0, getWidth(), getHeight(), this);
					}
					
				}
			};
			add(lcl_imagePanel, "width 100%, height 100%, span");
		}
		
		public	Image	getGeneratedTexture() {
			return mcl_generatedTexture.getImage();
		}
	}
	
	class	ProcTexturesPanel extends JPanel {
		private static final int IMAGE_DRAW_SIZE = 75;
		private		JPanel				mcl_textureDrawPanel;
		private		SimpleImageList		mcl_imageList;
		private		JTextField			mcl_low;
		private		JTextField			mcl_optimal;
		private		JTextField			mcl_high;
		
		public	ProcTexturesPanel() {
			setLayout(new MigLayout("inset 5"));
			
			JPanel		lcl_textureListPanel = new JPanel(new MigLayout("inset 5"));
			add(lcl_textureListPanel, "width 50%, height 100%");
			
			JPanel		lcl_btnPanel = new JPanel(new MigLayout("inset 5"));
			
			final	JButton		lcl_apply = SwingComponentFactory.makeAButton("Apply");
			
			// texture images
			mcl_imageList = new SimpleImageList(300, 400);
			mcl_imageList.setImageSelectionListener(new SimpleImageList.IImageSelectionListener() {
				public void imageSelected(SimpleImageList cl_list) {
					int		li_curSel = cl_list.getCurrentImageSelectionIndex();
					if(li_curSel == -1) {
						mcl_low.setText("");
						mcl_high.setText("");
						mcl_optimal.setText("");
						lcl_apply.setEnabled(false);
					} else {
						ProcTextureStruct		lcl_proc = mcla_textures.get(li_curSel);
						
						mcl_low.setText("" + lcl_proc.mi_low);
						mcl_optimal.setText("" + lcl_proc.mi_optimal);
						mcl_high.setText("" + lcl_proc.mi_high);
						lcl_apply.setEnabled(true);
					}
					
				}
			});
			
			JScrollPane		lcl_scroller = new JScrollPane();
			lcl_scroller.setViewportView(mcl_imageList);
			
			lcl_textureListPanel.add(lcl_scroller, "width 100%, height 100%");
			
			// texture params
			mcl_low = MigLayoutUtils.numberText(lcl_btnPanel, "Low", 0, true);
			mcl_optimal = MigLayoutUtils.numberText(lcl_btnPanel, "Optimal", 0, true);
			mcl_high = MigLayoutUtils.numberText(lcl_btnPanel, "High", 0, true);
			
			lcl_apply.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					int		li_low = Integer.parseInt(mcl_low.getText());
					int		li_optimal = Integer.parseInt(mcl_optimal.getText());
					int		li_high = Integer.parseInt(mcl_high.getText());
					
					ProcTextureStruct		lcl_proc = mcla_textures.get(mcl_imageList.getCurrentImageSelectionIndex());
					lcl_proc.mi_low = li_low;
					lcl_proc.mi_optimal = li_optimal;
					lcl_proc.mi_high = li_high;
				}
				
			});
			lcl_btnPanel.add(lcl_apply);
			lcl_apply.setEnabled(false);
			
			JButton		lcl_add = SwingComponentFactory.makeAButton("Add");
			lcl_add.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					File		lcl_file = GenericUtils.getAFile(null, false, false);
					if(lcl_file == null) { return; }
					
					try {
						final	ImageIcon		lcl_image = new ImageIcon(lcl_file.toURL());
						ProcTextureStruct		lcl_struct = new ProcTextureStruct(lcl_image, 0, 0, 0);
						mcla_textures.add(lcl_struct);
						mcl_imageList.addDrawImage(new SimpleImageList.IDrawImage() {
							public Image getImage() {
								return lcl_image.getImage();
							}
						});
						
						repaint();
					} catch (MalformedURLException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
				
			});
			lcl_btnPanel.add(lcl_add);
			
			add(lcl_btnPanel, "width 50%");
		}
	}
	
	class	ProcTextureStruct {
		public	int				mi_low;
		public	int				mi_optimal;
		public	int				mi_high;
		public	ImageIcon		mcl_image;
		
		public	ProcTextureStruct(ImageIcon cl_icon, int i_low, int i_optimal, int i_high) {
			mcl_image = cl_icon;
			mi_low = i_low;
			mi_optimal = i_optimal;
			mi_high = i_high;
		}
	}
}
